package ldh.im.fxgui.service;

import ldh.im.dto.business.item.CollectInfoItem;
import ldh.im.dto.business.item.MessageListItem;
import ldh.im.dto.business.message.MessageObject;
import ldh.im.dto.business.message.MessagePullByMessageIdsReq;
import ldh.im.fxbase.dao.ImMessageDao;
import ldh.im.fxbase.data.dto.RefMessageObject;
import ldh.im.fxbase.data.pojo.ImMessage;
import ldh.im.fxbase.rpc.service.RpcPullMessageService;
import ldh.im.fxbase.util.BeanFactory;
import ldh.im.fxbase.util.RpcUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.SQLException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 消息引用服务
 * 1，拉取未下载的引用消息
 */
public class MessageRefService {

    private static final Logger LOGGER = LoggerFactory.getLogger(MessageRefService.class);

    private ImMessageDao imMessageDao = BeanFactory.getInstance().getBean(ImMessageDao.class);
    private RpcPullMessageService rpcPullMessageService = RpcUtil.getRpcBootstrap().getRpcConfig().getClientBean(RpcPullMessageService.class);

    public List<MessageObject> pullRefMessages(String userId, List<String> serverIdList) throws SQLException {
        if (serverIdList.size() < 1) return new ArrayList<>();
        List<MessageObject> result = new ArrayList<>();

        // 处理有引用的消息
        List<MessageObject> messageObjectList = pullMessages(userId, serverIdList);
        messageObjectList = messageObjectList.stream().map(mo->new RefMessageObject(mo)).collect(Collectors.toList());
        result.addAll(messageObjectList);
        LOGGER.info("synData message ref size {}", messageObjectList.size());
        return result;
    }

    public List<MessageObject> pullCollectRefMessages(String userId, List<CollectInfoItem> collectInfoItems) throws SQLException {
        List<MessageObject> result = new ArrayList<>();

        // 处理有引用的消息
        List<String> serverIds = collectInfoItems.stream().map(m->m.getMessageId()).collect(Collectors.toList());
        List<MessageObject> messageObjects = pullMessages(userId, serverIds);
        result.addAll(messageObjects);
        LOGGER.info("synData message ref size {}", messageObjects.size());
        return result;
    }

    private List<MessageObject> pullMessages(String userId, List<String> serverIdList) throws SQLException {
        if (serverIdList.size() < 1) return new ArrayList<>();

        Set<String> serverIdSet = serverIdList.stream().collect(Collectors.toSet());
        List<ImMessage> dbMessages = imMessageDao.getByServerIdsAndUserId(serverIdSet, userId);
        Set<String> dbServerIdSet = dbMessages.stream().map(m->m.getServerId()).collect(Collectors.toSet());
        Set<String> noReceiveServerIdSet = serverIdSet.stream().filter(sid->!dbServerIdSet.contains(sid)).filter(s->s != null).collect(Collectors.toSet());

        if (noReceiveServerIdSet.size() < 1) return new ArrayList<>();

        List<MessageObject> result = new ArrayList<>();

        MessagePullByMessageIdsReq messagePullByMessageIdsReq = new MessagePullByMessageIdsReq();
        messagePullByMessageIdsReq.setServerMessageIdList(noReceiveServerIdSet.stream().collect(Collectors.toList()));
        MessageListItem messageListItem1 = rpcPullMessageService.pullMessageByMessageIds(messagePullByMessageIdsReq);
        List<MessageObject> messageObjectList = messageListItem1.getMessageObjectList().stream().map(mo->new RefMessageObject(mo)).collect(Collectors.toList());
        result.addAll(messageObjectList);

        Set<String> refServerIdSet = new HashSet<>();
        for (MessageObject messageObject : messageObjectList) {
            if (messageObject.isRef()) {
                List<String> refServerIds = Arrays.stream(messageObject.getRefMessageIds().split(",")).collect(Collectors.toList());
                refServerIdSet.addAll(refServerIds);
            }
        }

        result.addAll(pullMessages(userId, refServerIdSet.stream().collect(Collectors.toList())));

        return result;
    }

}
